package com.zu.commu.remote.session;

import com.zu.commu.context.ServerContext;
import org.apache.log4j.Logger;

import java.nio.channels.SocketChannel;
import java.util.*;
import java.util.Map.Entry;

public class SessionManager {
	private static HashMap<String, Session> GPRSID_map_Session;
	private static HashMap<SocketChannel, Session> channel_map_Session;
	private static SessionManager sm;
	private static FlagSocketOutLineThread flagThread;
	private static CleanSocketCommandIdThread cleanThread;
	Logger log = Logger.getLogger(SessionManager.class);
	private SessionManager() {
		
		GPRSID_map_Session = new HashMap<String, Session>();

		channel_map_Session = new HashMap<SocketChannel, Session>();

		flagThread = new FlagSocketOutLineThread();
		flagThread.start();
		log.debug("启动标记连接超时连接。。。");
		cleanThread = new CleanSocketCommandIdThread();
		cleanThread.start();
		log.debug("启动清除CommandId超时连接。。。");
	}

	public static SessionManager instance() {
		if (sm == null) {
			sm = new SessionManager();
		}
		return sm;
	}

	public void mapSession(String gprsId, Session se) {
		Session oldSe = (Session) GPRSID_map_Session.get(gprsId);
		if (oldSe == null) {
			GPRSID_map_Session.put(gprsId, se);
			channel_map_Session.put((SocketChannel) se.getAttribute("GPRSChannel"), se);
		} else {
			oldSe.close();
			channel_map_Session.remove((SocketChannel) oldSe.getAttribute("GPRSChannel"));
			oldSe = null;
			GPRSID_map_Session.put(gprsId, se);
			channel_map_Session.put((SocketChannel) se.getAttribute("GPRSChannel"), se);
		}
	}

	public Session getSessionByChannel(SocketChannel channel) {
		return (Session) channel_map_Session.get(channel);
	}

	public Session getSessionByGprsId(String gprsId) {
		return (Session) GPRSID_map_Session.get(gprsId);
	}

	public ArrayList getOnLineGprs() {
		ArrayList list = new ArrayList();
		Set cset = GPRSID_map_Session.entrySet();
		Iterator it = cset.iterator();
		Session se = null;
		while (it.hasNext()) {
			Map.Entry e = (Map.Entry) it.next();
			se = (Session) e.getValue();
			if ((se == null) || (((Boolean) se.getAttribute("GPRSIsClosed")).booleanValue()) || (!((Boolean) se.getAttribute("GPRSIsOnLine")).booleanValue()))
				continue;
			list.add((String) se.getAttribute("gprsId"));
		}

		return list;
	}

	private class CleanSocketCommandIdThread extends Thread {
		private CleanSocketCommandIdThread() {
		}

		public void run() {
			long sleepTime = ServerContext.cleanSocketCommandIdThreadSleepTime * 60L * 1000L;
			long commandActiveTime = ServerContext.commandIdExistTime * 60L * 1000L;
			boolean isException = false;
			while (true) {
				try {
					sleep(sleepTime);
				} catch (Exception e) {
					isException = true;
				}
				if (isException) {
					isException = false;
					continue;
				}
				Session se = null;
				Set set = SessionManager.GPRSID_map_Session.entrySet();
				Iterator it = set.iterator();
				while (it.hasNext()) {
					Map.Entry e = (Map.Entry) it.next();

					se = (Session) e.getValue();
					synchronized (se) {
						if (se != null) {
							ArrayList list = (ArrayList) se.getAttribute("GPRSCommands");
							if ((list != null) && (list.size() > 0)) {
								long now = System.currentTimeMillis();
								for (int i = 0; i < list.size(); i++) {
									CommandNode oo = (CommandNode) list.get(i);
									if ((oo == null) || (now - oo.genTime <= commandActiveTime))
										continue;
									list.remove(i);
									i--;
								}
							}
						}
					}
				}
			}
		}
	}

	private class FlagSocketOutLineThread extends Thread {
		private FlagSocketOutLineThread() {
		}

		public void run() {
			long sleepTime = ServerContext.flagSocketOutLineThreadSleepTime * 60L * 1000L;
			boolean isException = false;
			while (true) {
				try {
					sleep(sleepTime);
				} catch (Exception e) {
					isException = true;
				}
				if (isException) {
					isException = false;
					continue;
				}
				Session se = null;
				String needReturnHeartBeat = "0";
				String sendHeartBeat = "9";
				String GPRSprotocol = null;
				boolean needTest = false;
				int heartBeatTime = 2;
				Set<Entry<String, Session>> set = SessionManager.GPRSID_map_Session.entrySet();
				Iterator<Entry<String, Session>> it = set.iterator();
				while (it.hasNext()) {
					needTest = false;
					Entry<String, Session> e = it.next();
					se = e.getValue();
					synchronized (se) {
						if (se != null) {
							long now = System.currentTimeMillis();
							long old = ((Long) se.getAttribute("GPRSHeartBeatTime")).longValue();
							GPRSprotocol = (String) ServerContext.GPRSID_GPRSProtocol.get(se.getAttribute("gprsId"));
							if (GPRSprotocol == null) {
								Logger log = Logger.getLogger("com.automic.commu.remote.session.SessionManager$SessionManager");
								log.error("得到GPRSID:" + se.getAttribute("gprsId") + "的GPRS协议是空，不能标识是否在线！");
							} else if (ServerContext.GPRSProtocol_sendHeartBeat == null) {
								Logger log = Logger.getLogger("com.automic.commu.remote.session.SessionManager$SessionManager");
								log.error("服务器上下文ServerContext.GPRSProtocol_sendHeartBeat是空，不能标识是否在线！");
							} else {
								sendHeartBeat = (String) ServerContext.GPRSProtocol_sendHeartBeat.get(GPRSprotocol);
								if ((sendHeartBeat != null) && (sendHeartBeat.equals("0"))) {
									needTest = true;
								} else if ((sendHeartBeat != null) && (sendHeartBeat.equals("1"))) {
									needReturnHeartBeat = (String) ServerContext.GPRSProtocol_returnHeartBeat.get(GPRSprotocol);
									if (needReturnHeartBeat.equals("1")) {
										needTest = true;
									}
								} else if ((sendHeartBeat != null) && (sendHeartBeat.equals("9"))) {
									needTest = false;
								}
								if (needTest) {
									heartBeatTime = Integer.parseInt((String) ServerContext.GPRSProtocol_heartBeatTime.get(GPRSprotocol));

									if (now - old > heartBeatTime * ServerContext.noHearBeatTimes * 60 * 1000L)
										se.setAttribute("GPRSIsOnLine", new Boolean(false));
									else
										se.setAttribute("GPRSIsOnLine", new Boolean(true));
								}
							}
						}
					}
				}
			}
		}
	}
}
